package com.battery.system.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.response.AlipayTradePayResponse;
import com.battery.common.core.domain.AjaxResult;
import com.battery.common.core.text.Convert;
import com.battery.common.enums.*;
import com.battery.common.utils.BatteryJSONResult;
import com.battery.common.utils.Constants;
import com.battery.common.utils.DateUtils;
import com.battery.common.utils.GenerateSeqUtil;
import com.battery.common.utils.ali.AliPayEntity;
import com.battery.common.utils.ali.AliPayUtils;
import com.battery.common.utils.wx.PayscoreUtils;
import com.battery.system.domain.*;
import com.battery.system.domain.BO.EndorderBO;
import com.battery.system.domain.VO.EndorderVO;
import com.battery.system.mapper.*;
import com.battery.system.service.IEndorderService;
import org.apache.commons.lang3.StringUtils;
import org.n3r.idworker.Sid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 订单强制结束申请Service业务层处理
 *
 * @author battery
 * @date 2021-03-12
 */
@Service
public class EndorderServiceImpl extends BaseServiceImpl<Endorder> implements IEndorderService {


    @Autowired
    private EndorderMapper endorderMapper;


    @Autowired
    private UsedMapper usedMapper;


    @Autowired
    private UsedBasicsMapper usedBasicsMapper;


    @Autowired
    private AuthUsedMapper authUsedMapper;


    @Autowired
    private AppUserMapper appUserMapper;


    @Autowired
    private OrderMapper orderMapper;


    @Autowired
    private Sid sid;


    /**
     * 查询订单强制结束申请
     *
     * @param id 订单强制结束申请ID
     * @return 订单强制结束申请
     */
    @Override
    public Endorder selectEndorderById(String id) {
        return endorderMapper.selectEndorderById(id);
    }

    /**
     * 查询订单强制结束申请列表
     *
     * @param endorder 订单强制结束申请
     * @return 订单强制结束申请
     */
    @Override
    public List<Endorder> selectEndorderList(Endorder endorder) {
        return endorderMapper.selectEndorderList(endorder);
    }

    /**
     * 新增订单强制结束申请
     *
     * @param endorder 订单强制结束申请
     * @return 结果
     */
    @Override
    public int insertEndorder(Endorder endorder) {
        endorder.setCreateTime(DateUtils.getNowDate());
        return endorderMapper.insertEndorder(endorder);
    }

    /**
     * 修改订单强制结束申请
     *
     * @param endorder 订单强制结束申请
     * @return 结果
     */
    @Override
    public int updateEndorder(Endorder endorder) {
        return endorderMapper.updateEndorder(endorder);
    }

    /**
     * 删除订单强制结束申请对象
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteEndorderByIds(String ids) {
        return endorderMapper.deleteEndorderByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除订单强制结束申请信息
     *
     * @param id 订单强制结束申请ID
     * @return 结果
     */
    @Override
    public int deleteEndorderById(String id) {
        return endorderMapper.deleteEndorderById(id);
    }

    @Override
    public List<Endorder> selectEndorderByPartner(Map<String, String> map) {
        return endorderMapper.selectEndorderByPartner(map);
    }

    /**
     * 展示申请结束订单列表
     *
     * @param endorderBO
     * @return
     */
    @Override
    public List<EndorderVO> selectEndorderVOList(EndorderBO endorderBO) {
        return endorderMapper.selectEndorderVOList(endorderBO);
    }


    /**
     * 强制结束订单申请通过，并结束订单
     *
     * @param endorderBO
     * @param entity
     * @return
     */
    @Transactional
    @Override
    public AjaxResult forceEndUsed(EndorderBO endorderBO, AliPayEntity entity) {

        Date backDate = DateUtils.getNowDate(); // 归还时间
        BigDecimal needPay = endorderBO.getAmountPaid();

        Endorder endorder = endorderMapper.selectByPrimaryKey(endorderBO.getId());
        Endorder endorderUpdate = new Endorder();
        endorderUpdate.setAuditStatus(2); // 审核通过
        endorderUpdate.setAuditTime(backDate);
        endorderUpdate.setId(endorder.getId());
        endorderMapper.updateByPrimaryKeySelective(endorderUpdate);


        Used oldUsed = usedMapper.selectByPrimaryKey(endorder.getUsedId());
        Used usedUpdate = new Used();
        usedUpdate.setId(oldUsed.getId());
        usedUpdate.setIsBack(YesOrNoEnum.YES.getCode());
        usedUpdate.setAmountPaid(needPay);
        usedUpdate.setDiscountAmount(BigDecimal.ZERO);

        boolean isZero = false;
        if (needPay.subtract(BigDecimal.ZERO).compareTo(BigDecimal.ZERO) == 0) {
            // 零元订单结束
            usedUpdate.setStatus(UsedStatusEnum.PAID.getCode());
            usedUpdate.setPaymentTime(backDate);
            isZero = true;
        }
        usedMapper.updateByPrimaryKeySelective(usedUpdate);

        UsedBasics basicsUpdate = new UsedBasics();
        basicsUpdate.setUsedId(usedUpdate.getId());
        basicsUpdate.setIsBack(YesOrNoEnum.YES.getCode());
        basicsUpdate.setBackDate(backDate);
        usedBasicsMapper.updateByPrimaryKeySelective(basicsUpdate);

        Used used = usedMapper.selectByPrimaryKey(usedUpdate.getId());

        Integer channel = used.getChannel();
        Integer borrow_mode = used.getBorrowMode();
        if (isZero) {
            // 租借费用为0元，且
            if (borrow_mode == BorrowModeEnum.DEPOSIT.type) {
                // 押金租借
                return AjaxResult.success();
            }
            // 免押租借0元结束
            if (UserTypeEnum.WX.getCode().intValue() == channel.intValue()) {
                // 微信支付分0元结束
                BatteryJSONResult result = completeWxUsed(used.getId());
                if (result.getCode() == 1) {
                    return AjaxResult.success();
                } else {
                    return AjaxResult.error(result.getMsg());
                }
            } else {
                // 支付宝预授权0元结束
                BatteryJSONResult result = unfreezeToZero(used.getId(), entity);
                if (result.getCode() == 1) {
                    return AjaxResult.success();
                } else {
                    return AjaxResult.error(result.getMsg());
                }
            }
        }

        // 押金租借，非零元
        if (borrow_mode == BorrowModeEnum.DEPOSIT.type) {
            BatteryJSONResult result = depositEndUsed(used.getId(), backDate);
            if (result.getCode() == 1) {
                return AjaxResult.success();
            } else {
                return AjaxResult.error("发生错误！");
            }
        }

        if (UserTypeEnum.WX.getCode().intValue() == channel.intValue()) {
            // 微信租借，判断是押金租借，还是免押租借
            BatteryJSONResult result = completeWxUsed(used.getId());
            if (result.getCode() == 1) {
                return AjaxResult.success();
            }
        } else {
            // 支付宝预授权，授权转支付
            BatteryJSONResult result = freezeToPay(used.getId(), entity);
            if (result.getCode() == 1) {
                return AjaxResult.success();
            }
        }
        return AjaxResult.error();
    }

    /**
     * @param usedId
     * @return
     */
    @Override
    public Endorder selectOneByUsedId(String usedId) {
        return endorderMapper.selectOneByUsedId(usedId);
    }


    /**
     * 授权转支付
     *
     * @param used_id
     * @param entity
     * @return
     */
    private BatteryJSONResult freezeToPay(String used_id, AliPayEntity entity) {
        Used used = usedMapper.selectByPrimaryKey(used_id);

        BigDecimal amount = used.getAmountPaid();

        String order_id = sid.nextShort();
        String outOrderNo = GenerateSeqUtil.generateEndRadomCode() + GenerateSeqUtil.getRandomCode(6);
        // 首先创建对应的授权支付订单
        Order order = new Order();
        order.setId(order_id);
        order.setAppUserId(used.getAppUserId());
        order.setProjectId(used.getProjectId());
        order.setPartnerId(used.getPartnerId());
        order.setMerchantId(used.getMerchantId());
        order.setStoreId(used.getStoreId());
        order.setOutOrderNo(outOrderNo);
        order.setChannel(used.getChannel());
        order.setTotalFee(amount);
        order.setTradeState(OrderTradeStateEnum.UNPAID.getCode()); // 未支付

        UsedBasics basics = usedBasicsMapper.selectByPrimaryKey(used_id);
        order.setCreatedTime(DateUtils.getNowDate());
        order.setSn(basics.getRentDeviceSn());
        order.setPayType(OrderPayTypeEnum.ZFB_FREE.getCode()); // 支付宝预授权
        order.setOrderType(OrderTypeEnum.DEV_BORROW_COST.type);
        order.setUsedId(used_id);
        // 保存订单信息
        orderMapper.insertSelective(order);

        AuthUsed authUsed = authUsedMapper.selectByPrimaryKey(used_id);


        AppUser appUser = appUserMapper.selectByPrimaryKey(used.getAppUserId());

        // 新的商户交易流水号 outOrderNo
        // 解冻转支付标题，用于展示在支付宝账单中
        String subject = "免电" + "充电宝订单支付";
        BatteryJSONResult result = AliPayUtils.tradePay(entity, outOrderNo, authUsed.getAuthNo(), subject, amount, appUser.getAppUserCode(), Constants.ali_freeze_pay_url);
        if (result.getCode() == 0) {
            // TODO 扣款失败，注意要记录对应的支付宝交易号
            AlipayTradePayResponse response = (AlipayTradePayResponse) result.getData();
            String trade_no = response.getTradeNo();
            if (StringUtils.isNotBlank(trade_no)) {
                Order updateOrder = new Order();
                updateOrder.setId(order_id);
                updateOrder.setTransactionId(trade_no); // 支付宝交易号（支付失败的情况下，该订单号非常重要）
                orderMapper.updateByPrimaryKeySelective(updateOrder);
            }

            Used usedUpdate = new Used();
            usedUpdate.setId(used_id);
            usedUpdate.setTrueOrderId(order_id);
            usedMapper.updateByPrimaryKeySelective(usedUpdate);
            return BatteryJSONResult.errorMsg(result.getMsg());
        }

        // 授权订单完成
        AuthUsed authUsedUpdate = new AuthUsed();
        authUsedUpdate.setUsedId(used_id);
        authUsedUpdate.setState(UsedAuthStateEnum.DONE.type);
        authUsedMapper.updateByPrimaryKeySelective(authUsedUpdate);

        Used usedUpdate = new Used();
        usedUpdate.setId(used_id);
        usedUpdate.setTrueOrderId(order_id);
        usedMapper.updateByPrimaryKeySelective(usedUpdate);

        AlipayTradePayResponse response = (AlipayTradePayResponse) result.getData();
        String trade_no = response.getTradeNo();
        Order updateOrder = new Order();
        updateOrder.setId(order_id);
        updateOrder.setTransactionId(trade_no);
        orderMapper.updateByPrimaryKeySelective(updateOrder);
        return BatteryJSONResult.ok();
    }


    /**
     * 押金结束订单
     *
     * @param used_id
     * @return
     */
    private BatteryJSONResult depositEndUsed(String used_id, Date backDate) {
        Used used = usedMapper.selectByPrimaryKey(used_id);

        // 查询该用户未使用押金
        Example example = new Example(Order.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("appUserId", used.getAppUserId());
        criteria.andEqualTo("channel", used.getChannel());
        criteria.andEqualTo("tradeState", OrderTradeStateEnum.PAY_SUCCESS.getCode());
        criteria.andEqualTo("orderType", OrderTypeEnum.DEPOSIT.type);
        criteria.andEqualTo("isUsed", YesOrNoEnum.YES.getCode());
        Order noUsedDeposit = orderMapper.selectOneByExample(example);
        if (noUsedDeposit != null && noUsedDeposit.getTotalFee().subtract(used.getAmountPaid()).compareTo(BigDecimal.ZERO) == 0) {
            // 存在未使用押金，且扣款金额等于押金金额
            // 直接将押金设置为已使用
            Order orderUpdate = new Order();
            orderUpdate.setId(noUsedDeposit.getId());
            orderUpdate.setIsUsed(YesOrNoEnum.YES.getCode());
            orderUpdate.setUsedId(used_id);
            orderMapper.updateByPrimaryKeySelective(orderUpdate);

            // 同时更新对应租借记录
            Used usedUpdate = new Used();
            usedUpdate.setId(used_id);
            usedUpdate.setStatus(UsedStatusEnum.PAID.getCode());
            usedUpdate.setPaymentTime(backDate);

            // TODO TODO 开始99元分成操作

            return BatteryJSONResult.ok();
        }

        AppUser appUser = appUserMapper.selectByPrimaryKey(used.getAppUserId());
        AppUser appUserUpdate = new AppUser();
        appUserUpdate.setId(appUser.getId());
        appUserUpdate.setBalance(appUser.getBalance().subtract(used.getAmountPaid()));
        appUserUpdate.setUpdateTime(backDate);
        appUserMapper.updateByPrimaryKeySelective(appUserUpdate);

        // TODO TODO 开始分成

        return BatteryJSONResult.ok();
    }


    /**
     * 微信支付分结束订单
     *
     * @param used_id
     * @return
     */
    private BatteryJSONResult completeWxUsed(String used_id) {

        Used used = usedMapper.selectByPrimaryKey(used_id);

        BigDecimal amount = used.getAmountPaid();

        JSONObject obj = new JSONObject();
        obj.put("appid", Constants.wxMinAppID);
        obj.put("service_id", Constants.wxServiceId);
        // 开电共享充电宝,租赁费用
        String serviceIntroduction = "免电共享充电宝" + "," + "租赁费用";
        JSONArray array = new JSONArray();
        JSONObject postPaymentsObj = new JSONObject();
        postPaymentsObj.put("name", serviceIntroduction);
        postPaymentsObj.put("amount", amount.multiply(new BigDecimal(100))); // 金额
        array.add(postPaymentsObj);
        obj.put("post_payments", array);
        obj.put("total_amount", amount.multiply(new BigDecimal(100)));
        JSONObject timeRangeObj = new JSONObject();
        timeRangeObj.put("end_time", DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS, DateUtils.getNowDate()));
        obj.put("time_range", timeRangeObj);
        JSONObject locationObj = new JSONObject();
        locationObj.put("end_location", used.getStoreName());
        obj.put("Location", locationObj);
        BatteryJSONResult response = null;
        AuthUsed authUsed = authUsedMapper.selectByPrimaryKey(used_id);
        try {
            response = PayscoreUtils.complete(obj, authUsed.getOutOrderNo(), Constants.wxMerchantId, Constants.certSerialNo, Constants.wx_cret_keyPath_apiclient_key);
        } catch (Exception e) {
            e.printStackTrace();
            return BatteryJSONResult.errorMsg("完结微信支付分订单失败");
        }
        if (response == null) {
            return BatteryJSONResult.errorMsg("完结微信支付分订单失败");
        }
        if (response.getCode() == 0) {
            return response;
        }
        String body = (String) response.getData();
        JSONObject obj_ = JSONObject.parseObject(body);
        if (StringUtils.isNotBlank(obj_.getString("code"))) {
            return BatteryJSONResult.errorMsg("完结微信支付分订单失败");
        }
        String state = obj_.getString("state");
        if ("DOING".equals(state) || "DONE".equals(state)) {
            AuthUsed updateAuthUsed = new AuthUsed();
            updateAuthUsed.setUsedId(used_id);
            updateAuthUsed.setState(state);
            authUsedMapper.updateByPrimaryKeySelective(updateAuthUsed);
        }
        return BatteryJSONResult.ok();
    }


    /**
     * 预授权租借0元结束订单，解冻处理
     *
     * @param used_id
     * @return
     */
    private BatteryJSONResult unfreezeToZero(String used_id, AliPayEntity entity) {

        AuthUsed authUsed = authUsedMapper.selectByPrimaryKey(used_id);
        String auth_no = authUsed.getAuthNo();
        String out_request_no = authUsed.getTicket();
        BigDecimal amount = authUsed.getAmount();
        BatteryJSONResult reponseResult = AliPayUtils.unfreeze(entity, auth_no, out_request_no, amount);
        boolean isSuc = false;
        if (reponseResult.getCode() == 0) {
            JSONObject responseJSON = (JSONObject) reponseResult.getData();
            String subCode = responseJSON.getString("sub_code");
            if ("ORDER_ALREADY_FINISH".equals(subCode) || "ORDER_ALREADY_CLOSED".equals(subCode)) {
                isSuc = true;
            }
        } else {
            isSuc = true;
        }
        if (isSuc) {
            // 解冻成功，更新状态
            AuthUsed authUsedUpdate = new AuthUsed();
            authUsedUpdate.setUsedId(used_id);
            authUsedUpdate.setState(UsedAuthStateEnum.PAID.type); // 订单已支付
            authUsedUpdate.setStateDescription(UsedAuthStateDescriptionEnum.USER_PAID.type); // 订单已支付
            authUsedMapper.updateByPrimaryKeySelective(authUsedUpdate);
            return BatteryJSONResult.ok();
        }
        return BatteryJSONResult.errorMsg("解冻授权订单出现错误");
    }


}

